// This file is part of OpenMeca, an easy software to do mechanical simulation.
//
// Author(s)    :  - Damien ANDRE  <openmeca@gmail.com>
//
// Copyright (C) 2012 Damien ANDRE
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


#ifndef OpenMeca_WidgetSelectItem_HPP
#define OpenMeca_WidgetSelectItem_HPP


#include <QWidget>
#include <QBoxLayout>
#include <QLabel>
#include <QComboBox>


#include "OpenMeca/Core/System.hpp"
#include "OpenMeca/Core/UserItem.hpp"
#include "OpenMeca/Gui/WidgetInterface.hpp"


namespace OpenMeca
{
  namespace Gui
  {

    class AbstractWidgetSelectItem :  public QWidget
    {
       Q_OBJECT

     public:
      AbstractWidgetSelectItem(QWidget* parent);
      virtual ~AbstractWidgetSelectItem();
      void SetLabel(const QString&);
      QComboBox& GetComboBox();							     

    protected:
      virtual void ItemSelected_CallBack(Core::UserItem&) = 0;
      void ClearComboBox();
      QLabel& GetLabel();
      
      virtual void hideEvent(QHideEvent *event);
      virtual void showEvent(QShowEvent *event);
							


    public slots:
      void ItemSelected(Core::UserItem&);

    private:
     QHBoxLayout *horizontalLayout_;
     QLabel *label_;
     QComboBox *comboBox_;
    };

    
    template<class T>
    class WidgetSelectItem: public AbstractWidgetSelectItem,  public WidgetInterface<T>
    {
      
    public:
      WidgetSelectItem(QWidget* parent);
      virtual ~WidgetSelectItem();

      bool Check();
      void ApplyValue();
      typename T::PtrType& GetSelectedItem();

    private:
      void Init();
      typename T::PtrType& GetItemAtIndex(int i);
      int GetIndexForItem(typename T::PtrType& item);
      void ItemSelected_CallBack(Core::UserItem&);


    private:
      std::map<unsigned int, typename T::PtrType*> map_;

    private:
      
    };


    template<class T>
    inline
    WidgetSelectItem<T>::WidgetSelectItem(QWidget* parent)
      :AbstractWidgetSelectItem(parent),
       WidgetInterface<T>(*parent),
       map_()
    {
    
    }
    

    template<class T>
    inline
    WidgetSelectItem<T>::~WidgetSelectItem()
    {
    }


    template<class T>
    inline typename T::PtrType& 
    WidgetSelectItem<T>::GetItemAtIndex(int i)
    {
      assert(map_.count(i)==1);
      return *map_[i];
    }

    template<class T>
    inline int
    WidgetSelectItem<T>::GetIndexForItem(typename T::PtrType& item)
    {
      typename std::map<unsigned int, typename T::PtrType*>::iterator it;
      for ( it=map_.begin() ; it != map_.end(); it++ )
	{
	  if ((*it).second == &item)
	    return (*it).first;
	}
      assert(0); //Problem can't find item
      return -1;
    }
    
    template<class T>
    inline void 
    WidgetSelectItem<T>::Init()
    {
      AbstractWidgetSelectItem::ClearComboBox();
      Core::SetOf<typename T::PtrType>& set = Core::System::Get().GetSetOf<typename T::PtrType>();
      typename std::list<typename T::PtrType*>::iterator it;
      unsigned int index = 0;
      map_.clear();
      for (it=set.Begin() ; it != set.End(); it++ )
	{
	  map_[index] = *it;
	  const typename T::PtrType& item = **it;
	  AbstractWidgetSelectItem::GetComboBox().addItem(item.GetIcon(), item.GetName().c_str());
	  index ++;
	}
      const int currentIndex = GetIndexForItem(*WidgetInterface<T>::GetCopy().GetPtr());
      AbstractWidgetSelectItem::GetComboBox().setCurrentIndex(currentIndex);
    }
    

   
    template<class T>
    inline bool
    WidgetSelectItem<T>::Check()
    {
      WidgetInterface<T>::GetCopy() = &GetSelectedItem();
      return true;
    }



    template<class T>
    inline typename T::PtrType&
    WidgetSelectItem<T>::GetSelectedItem()
    {
      return GetItemAtIndex(AbstractWidgetSelectItem::GetComboBox().currentIndex());
    }

     template<class T>
     inline void 
     WidgetSelectItem<T>::ItemSelected_CallBack(Core::UserItem& item)
     {
       if (typeid(typename T::PtrType)==typeid(item))
       	 {
       	   typename T::PtrType& cast = static_cast<typename T::PtrType&>(item);
       	   AbstractWidgetSelectItem::GetComboBox().setCurrentIndex(GetIndexForItem(cast));
       	 }
     }

  }
}
#endif

